#include "choosefrienddialog.h"

#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QPushButton>
#include <QScrollArea>
#include <QScrollBar>

#include "debug.h"
#include "toast.h"
#include "model/datacenter.h"
#include "utils/widgetuitl.hpp"


/* =========================================== *
 *           拉人建群窗口界面实现                 *
 * =========================================== */
ChooseFriendDialog::ChooseFriendDialog(QWidget* parent, const QString& userId)
    : QDialog(parent), userId(userId)
{
    // 1.设置窗口基本属性
    this->setStyleSheet("QWidget { background-color: rgb(255, 255, 255); }");
    this->setFixedSize(750, 550);
    this->setWindowTitle("选择好友");
    this->setWindowIcon(QIcon(":/resource/image/logo.png"));
    this->setAttribute(Qt::WA_DeleteOnClose);

    // 2.整体水平布局
    QHBoxLayout* layout = new QHBoxLayout();
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    this->setLayout(layout);

    initLeftList(layout);
    initRightList(layout);

    initData();
}

void ChooseFriendDialog::initLeftList(QHBoxLayout* layout)
{
    // 1.创建滚动区域
    QScrollArea* scrollArea = utils::WidgetUtil::createQScrollArea();
    layout->addWidget(scrollArea, 1);   // 指定整个layout左右两块布局的拉伸系数为1:1, 即等宽布局

    // 2.创建滚动区域的参照widget对象
    totalContainer = new QWidget();
    totalContainer->setObjectName("totalContainer");
    totalContainer->setStyleSheet("#totalContainer { background-color: rgb(255, 255, 255); }");
    scrollArea->setWidget(totalContainer);

    // 3.左侧自身的垂直布局(这个布局管理器是给totalContainer的, 也就是实际存放左侧列表元素的布局)
    QVBoxLayout* leftLayout = new QVBoxLayout();
    leftLayout->setSpacing(0);
    leftLayout->setContentsMargins(0, 0, 0, 0);
    leftLayout->setAlignment(Qt::AlignTop);
    totalContainer->setLayout(leftLayout);

/////////测试数据
#if TEST_UI
    QIcon icon(":/resource/image/girl.jpg");
    for(int i = 0; i < 30; ++i) {
        addFriendItem(QString::number(i), icon, "小美" + QString::number(i), false);
    }
#endif
}

void ChooseFriendDialog::initRightList(QHBoxLayout* layout)
{
    /// 1.创建右侧整体网格布局
    /// 顶部标签
    /// 选中好友项
    /// 按钮 按钮
    QGridLayout* rightLayout = new QGridLayout();
    rightLayout->setContentsMargins(20, 0, 20, 20);
    rightLayout->setSpacing(10);
    layout->addLayout(rightLayout, 1);

    // 2.创建顶部文本标签
    QLabel* tipLabel = new QLabel();
    tipLabel->setText("选择联系人");
    tipLabel->setFixedHeight(30);
    tipLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    tipLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    tipLabel->setStyleSheet("QLabel { font-size:16px; font-weight: 700; }");

    // 3.创建滚动区域
    QScrollArea* scrollArea = utils::WidgetUtil::createQScrollArea();

    // 4.创建滚动参照窗口
    selectedContainer = new QWidget();
    selectedContainer->setObjectName("selectedContainer");
    selectedContainer->setStyleSheet("#selectedContainer { background-color: rgb(255, 255, 255); }");
    scrollArea->setWidget(selectedContainer);

    // 5.创建垂直布局(中间选中好友项布局）
    QVBoxLayout* selectLayout = new QVBoxLayout();
    selectLayout->setSpacing(0);
    selectLayout->setContentsMargins(0, 0, 0, 0);
    selectLayout->setAlignment(Qt::AlignTop);
    selectedContainer->setLayout(selectLayout);

    // 6.底部按钮
    QString style = "QPushButton { color: rgb(7, 193, 96); background-color: rgb(243, 243, 243); border: none; border-radius: 5px; } "
                    "QPushButton:hover { background-color: rgb(219, 219, 219); }"
                    "QPushButton:pressed { background-color: rgb(206, 206, 206); }";
    QPushButton* finishBtn = new QPushButton();
    finishBtn->setText("完成");
    finishBtn->setFixedHeight(40);
    finishBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    finishBtn->setStyleSheet(style);

    QPushButton* cancelBtn = new QPushButton();
    cancelBtn->setText("取消");
    cancelBtn->setFixedHeight(40);
    cancelBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    cancelBtn->setStyleSheet(style);

    // 7.网格行列布局
    rightLayout->addWidget(tipLabel, 0, 0, 1, 9);
    rightLayout->addWidget(scrollArea, 1, 0, 1, 9);
    rightLayout->addWidget(finishBtn, 2, 1, 1, 3);
    rightLayout->addWidget(cancelBtn, 2, 5, 1, 3);


/////////测试数据
#if TEST_UI
    QIcon icon(":/resource/image/girl.jpg");
    for(int i = 30; i < 40; ++i) {
        addSelectedFriendItem("30" + QString::number(i), icon, "小美" + QString::number(i));
    }
#endif

    connect(finishBtn, &QPushButton::clicked, this, &ChooseFriendDialog::onClickedByFinishBtn);
    connect(finishBtn, &QPushButton::clicked, this, [=](){
        this->close();
    });
}

void ChooseFriendDialog::initData()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::UserInfo>* friendList = dataCenter->getFriendList();
    if(!friendList) {
        LOG(LL_ERROR, "错误行为, 好友列表没有加载到程序中");
        return;
    }
    for(auto& f : *friendList) {
        if(f.userId == this->userId) {
            this->addSelectedFriendItem(f.userId, f.avatar, f.nickname);
            this->addFriendItem(f.userId, f.avatar, f.nickname, true);
        } else {
            this->addFriendItem(f.userId, f.avatar, f.nickname, false);
        }
    }
}

void ChooseFriendDialog::onClickedByFinishBtn()
{
    QList<QString> userIdList = generateMemberList();
    if(userIdList.size() < 3) {
        Toast::showMessage("选中成员小于3个, 无法创建群聊");
        return;
    }

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->createGroupChatSessionAsync(userIdList);

    this->close();
}

QList<QString> ChooseFriendDialog::generateMemberList()
{
    QList<QString> memberList;

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    model::UserInfo* selfInfo = dataCenter->getSelfInfo();
    if(!selfInfo) {
        LOG(LL_ERROR, "错误行为, 个人信息未正确初始化");
        return memberList;
    }
    memberList.emplace_back(selfInfo->userId);

    QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(selectedContainer->layout());
    for(int i = 0; i < layout->count(); ++i) {
        QLayoutItem* item = layout->itemAt(i);
        if(!item || !item->widget()) {
            continue;
        }
        ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());
        memberList.emplace_back(chooseFriendItem->getUserId());
    }
    return memberList;  // C++17 NRVO机制, 不需要拷贝
}


void ChooseFriendDialog::addFriendItem(const QString& userId, const QIcon& avatar, const QString& name, bool checked)
{
    ChooseFriendItem* chooseFriendItem = new ChooseFriendItem(this, userId, avatar, name, checked);
    totalContainer->layout()->addWidget(chooseFriendItem);
}

void ChooseFriendDialog::addSelectedFriendItem(const QString& userId, const QIcon &avatar, const QString &name)
{
    ChooseFriendItem* chooseFriendItem = new ChooseFriendItem(this, userId, avatar, name, true);
    selectedContainer->layout()->addWidget(chooseFriendItem);
}

void ChooseFriendDialog::removeSelectedFriendItem(const QString &userId)
{
    // 删除右边列表已选择的item
    QVBoxLayout* selectLayout = dynamic_cast<QVBoxLayout*>(selectedContainer->layout());
    for(int i = selectLayout->count() - 1; i >= 0; --i) {
        QLayoutItem* item = selectLayout->itemAt(i);
        if(!item || !item->widget()) {
            return;
        }
        ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());
        if(chooseFriendItem->getUserId() != userId) {
            continue;
        }
        selectLayout->removeWidget(chooseFriendItem);

        // 该函数是在信号槽中执行的, 而信号槽的是在ChooseFriendItem内部中调用的,
        // 如果ChooseFriendItem本身都被释放了, 待removeSelectedFriendItem返回到信号槽内部时就出问题
        chooseFriendItem->deleteLater();
    }

    // 移除左边复选框选中效果
    QVBoxLayout* leftLayout = dynamic_cast<QVBoxLayout*>(totalContainer->layout());
    for(int i = 0; i < leftLayout->count(); ++i) {
        QLayoutItem* item = leftLayout->itemAt(i);
        if(!item || !item->widget()) {
            return;
        }
        ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());
        if(chooseFriendItem->getUserId() != userId) {
            continue;
        }
        chooseFriendItem->getCheckBox()->setChecked(false);
    }
}


/* =========================================== *
 *           选择好友自定义控件类对象实现           *
 * =========================================== */
ChooseFriendItem::ChooseFriendItem(ChooseFriendDialog* owner, const QString& userId, const QIcon& avatar, const QString& name, bool checked)
    : isHover(false), userId(userId)
{
    // 1.设置好友控件的基本属性
    this->setFixedHeight(50);
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 2.水平布局(复选框 头像 名字)
    QHBoxLayout* layout = new QHBoxLayout();
    layout->setSpacing(10);
    layout->setContentsMargins(20, 0, 20, 0);
    this->setLayout(layout);

    checkBox = new QCheckBox();
    checkBox->setChecked(checked);
    checkBox->setFixedSize(25, 25);
    checkBox->setStyleSheet("QCheckBox { background-color: transparent; }"
                            "QCheckBox::indicator { width: 20px; height: 20px; image: url(:/resource/image/unchecked.png); }"
                            "QCheckBox::indicator:checked { image: url(:/resource/image/checked.png); }");

    avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(40, 40);
    avatarBtn->setIconSize(QSize(40, 40));
    avatarBtn->setIcon(avatar);
    avatarBtn->setStyleSheet(" QPushButton { border: none;  background-color: transparent; }");

    QLabel* nameLabel = new QLabel();
    nameLabel->setText(name);
    nameLabel->setStyleSheet("QLabel { background-color: transparent; }");

    layout->addWidget(checkBox);
    layout->addWidget(avatarBtn);
    layout->addWidget(nameLabel);

    connect(checkBox, &QPushButton::toggled, this, [=](bool checked){
        if(checked) {
            owner->addSelectedFriendItem(userId, avatar, name);
        } else {
            owner->removeSelectedFriendItem(userId);
        }
    });
}

QString ChooseFriendItem::getUserId()
{
    return userId;
}

QCheckBox *ChooseFriendItem::getCheckBox()
{
    return checkBox;
}

void ChooseFriendItem::paintEvent(QPaintEvent* event)
{
    (void)event;
    QPainter painter(this);
    if(isHover) {
        painter.fillRect(this->rect(), QColor(231, 231, 231));
    } else {
        painter.fillRect(this->rect(), QColor(255, 255, 255));
    }
}

void ChooseFriendItem::enterEvent(QEnterEvent* event)
{
    (void)event;
    isHover = true;
    this->update();     //更新界面
}

void ChooseFriendItem::leaveEvent(QEvent* event)
{
    (void)event;
    isHover = false;
    this->update();     //更新界面
}

